#lang racket

(require racket/match)

(define builtins
  `((car . ,car)
    (cdr . ,cdr)
    (cons . ,cons)
    (+ . ,+)
    (- . ,-)
    (* . ,*)
    (/ . ,/)))

(define special-forms
  '(lambda))

(define (i exp env spec)
  (match exp
    ((? number? n) n)
    ((? symbol? s)
     (cond ((assoc s env) => cdr)
	   (else (error "unbound variable" s))))
    ((? list? l)
     (if (member (car l) spec)
	 (i-special l env spec)
	 (apply (i (car l) env spec)
		(map (lambda (exp) (i exp env spec)) (cdr l)))))
    (else (error "unknown expression type" exp))))

(define (i-special exp env spec)
  (match exp
    (`(lambda (,x) ,b)
     (lambda (y)
       (i b (cons (cons x y) env) (remove x spec))))
    (else (error "Unimplemented special form:" exp))))

;; > (i '(+ 7 (car (cons 3 5))) builtins)
;; 10
